package com.leetroll.api.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.leetroll.api.mapper.ItemMapper;
import com.leetroll.api.service.*;
import com.leetroll.common.constant.SQLConstant;
import com.leetroll.common.entity.*;
import com.leetroll.common.enums.EFileType;
import com.leetroll.common.enums.EItemType;
import com.leetroll.common.enums.EUserAction;
import com.leetroll.common.utils.StringUtils;
import com.leetroll.common.utils.UserUtil;
import com.leetroll.common.vo.ChapterVO;
import com.leetroll.common.vo.FileVO;
import com.leetroll.common.vo.ItemVO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

import static com.leetroll.common.utils.AliyunOSSUtil.GetUrl;

@Service
public class ItemServiceImpl extends SuperServiceImpl<ItemMapper, Item> implements ItemService {

    private final FileService fileService;
    private final UserActionService userActionService;
    private final OrderService orderService;
    private final ChapterService chapterService;
    private final TagService tagService;

    @Autowired
    public ItemServiceImpl(FileService fileService, UserActionService userActionService, OrderService orderService, ChapterService chapterService, TagService tagService) {
        this.fileService = fileService;
        this.userActionService = userActionService;
        this.orderService = orderService;
        this.chapterService = chapterService;
        this.tagService = tagService;
    }

    /**
     * 查询该分类下的4条最热门item
     *
     * @param category 分类
     */
    @Cacheable(cacheNames = "listHot4Items", key = "#category.id")
    public List<ItemVO> listHot4Items(Category category) {
        QueryWrapper<Item> queryWrapper = new QueryWrapper<>();
        queryWrapper.ne("type", EItemType.IMAGE.getType());
        if (category.getName().equals(EItemType.SOUND.getType())) {
            queryWrapper.eq(SQLConstant.ITEM_CAT_ID, category.getId()).last("limit 2");
        } else {
            queryWrapper.eq(SQLConstant.ITEM_CAT_ID, category.getId()).last("limit 4");
        }
        if (category.getId() == 7) {
            queryWrapper.eq(SQLConstant.ITEM_TYPE, EItemType.MODEL_BUNDLE.getType());
        }
        List<Item> itemList = this.list(queryWrapper);
        //组装item资源
        return itemList.stream()
                .map(ItemVO::fromItem)
                .peek(this::enrichUserAction)
                .peek(item -> {
                    if (item.getBought()) {
                        enrichAttach(item);
                    }
                })
                .map(v -> enrichFiles(v, false))
                .collect(Collectors.toList());
    }

    @Override
    public Integer totalSize(Integer catId, String keyword) {
        QueryWrapper<Item> queryWrapper = new QueryWrapper<>();
        if (catId != null && catId != 0) {
            queryWrapper.eq("cat_id", catId);
        }

        makeQuery(queryWrapper, keyword);

        //组装item资源
        return this.list(queryWrapper).size();
    }

    @Override
    @Cacheable(cacheNames = "listByAction")
    public List<ItemVO> listByActionAndUser(String action, Integer pageNumber, Integer pageSize) {
        int[] itemIds = userActionService.listItemIdsByActionAndUser(action, pageNumber, pageSize);
        if (itemIds == null || itemIds.length == 0) return new ArrayList<>();
        return Arrays.stream(itemIds).mapToObj(this::getById).collect(Collectors.toList());
    }


    @Override
    @Cacheable(cacheNames = "getById", key = "#id")
    public ItemVO getById(Integer id) {
        ItemVO itemVO = getBasicById(id);
        return enrichFiles(itemVO, false);
    }

    /**
     * 分页查询item信息
     *
     * @param keyword 搜索关键词
     * @param catId   分类id
     */
    @Override
    @Cacheable(cacheNames = "listItemsByPage")
    public List<ItemVO> listItems(Integer catId, Integer pageNumber, String keyword) {
        Page<Item> page = new Page<>(pageNumber, 12);
        QueryWrapper<Item> queryWrapper = new QueryWrapper<>();
        if (catId != null && catId != 0) {
            queryWrapper.eq("cat_id", catId);
        }
        makeQuery(queryWrapper, keyword);
        List<Item> itemList = this.page(page, queryWrapper).getRecords();

        //组装item资源
        return itemList.stream()
                .map(ItemVO::fromItem)
                .peek(this::enrichUserAction)
                .map(v -> enrichFiles(v, false))
                .collect(Collectors.toList());
    }

    private void makeQuery(QueryWrapper<Item> queryWrapper, String keywords) {
        if (StringUtils.isEmpty(keywords)) {
            return;
        }
        String[] strings = keywords.split("-");
        for (String keyword : strings) {
            if (keyword.equals("all") || StringUtils.isEmpty(keyword.trim())) {
                continue;
            }
            Tag tag = tagService.getByWord(keyword);
            if (tag != null) keyword = tag.getTag().trim();

            String finalKeyword = keyword;
            queryWrapper.and(wrapper -> {
                for (String key : finalKeyword.split(" ")) {
                    if (StringUtils.isEmpty(key.trim())) continue;
                    String replaced = key.replace(")", "").replace("(", "");
                    wrapper.like("LOWER(name)", replaced.toLowerCase())
                            .or()
                            .like("LOWER(tag)", replaced.toLowerCase())
                            .or()
                            .like("LOWER(desp)", replaced.toLowerCase())
                            .or();
                }
            });
        }
    }

    /**
     * 获取item详细信息
     */
    @Override
    @Cacheable(cacheNames = "getAllInfoById", key = "#itemId")
    public ItemVO getAllInfoById(Integer itemId) {
        ItemVO itemVO = getBasicById(itemId);

        //enrich item表现信息
        enrichBehavior(itemVO);

        //补充用户行为信息
        enrichUserAction(itemVO);

        //enrich files 信息(预览图和附件信息)
        enrichFiles(itemVO, true);

        //enrich章节信息 (如果item是教程类资源)
        if (!itemVO.getType().equals(EItemType.TUTORIAL.getType())) return itemVO;
        List<ChapterVO> chapterVOS = chapterService.getAllByItemId(itemVO.getId());
        itemVO.setChapters(chapterVOS);

        return itemVO;
    }

    @Override
    public String downloadAttachment(Integer itemId) {
        File file = fileService.getAttachByRescId(itemId);
        return GetUrl(file.getBucket(), file.getKey() + file.getName() + "." + file.getSuffix());
    }

    @Override
    public void updatePrice(Integer id, Double price) {
        Item item = super.getById(id);
        item.setPrice(price);
        item.updateById();
    }

    @Override
    public void updateTag(Integer id, String tag) {
        Item item = super.getById(id);
        item.setTag(tag);
        item.updateById();
    }

    /**
     * 组装item的表现信息
     */
    private void enrichBehavior(ItemVO itemVO) {
        //资源表现信息 (下载次数, 被赞次数, 被收藏次数)
        Map<String, Long> actionMap = userActionService.countByItemIdAndAcion(itemVO.getId().intValue());
        itemVO.setLikeCnt(actionMap.getOrDefault(EUserAction.LIKE.getAction(), 0L).intValue());
        itemVO.setCollectCnt(actionMap.getOrDefault(EUserAction.COLLECT.getAction(), 0L).intValue());
        itemVO.setDownCnt(0);
    }

    /**
     * item的用户行为信息
     */
    private void enrichUserAction(ItemVO itemVO) {
        Long userId = UserUtil.getUserId();
        if (userId == null || itemVO == null) return;
        //enrich 用户行为信息
        UserAction like = userActionService.getByAction(itemVO.getId(), EUserAction.LIKE.getAction());
        UserAction collect = userActionService.getByAction(itemVO.getId(), EUserAction.COLLECT.getAction());
        itemVO.setLiked(like != null && like.getValue());
        itemVO.setCollected(collect != null && collect.getValue());

        //检查user是否已经购买过该资源
        boolean exist = orderService.checkIfUserOwnItem(userId, itemVO.getId().intValue());
        itemVO.setBought(itemVO.getPrice().equals(0.0) || exist);
    }

    private ItemVO getBasicById(Integer id) {
        Item item = super.getById(id);
        return ItemVO.fromItem(item);
    }

    /**
     * 组装item的file信息  (主图默认组装)
     *
     * @param itemVO    itemvo
     * @param withPrevs 是否组装预览图
     */
    private ItemVO enrichFiles(ItemVO itemVO, boolean withPrevs) {
        //item file信息
        QueryWrapper<File> fileQueryWrapper = new QueryWrapper<>();
        fileQueryWrapper.eq(SQLConstant.FILE_RESC_ID, itemVO.getId());
        List<File> files = fileService.list(fileQueryWrapper);
        Map<String, List<File>> map = files.stream().collect(Collectors.groupingBy(File::getType));

        //enrich 主图信息
        if (map.containsKey(EFileType.MAIN.getType())) {
            File file = map.get(EFileType.MAIN.getType()).get(0);
            FileVO fileVO = FileVO.fromFile(file);
            fileVO.setLink(GetUrl(file.getBucket(), file.getKey() + file.getName() + "." + file.getSuffix()));
            itemVO.setMain(fileVO);
        }

        if (!withPrevs) return itemVO;

        //enrich 附件信息 (只有附件格式， 不包含附件下载url)
        List<FileVO> attachments = map.getOrDefault(EFileType.ATTACHMENT.getType(), new ArrayList<>()).stream().map(file -> {
            FileVO fileVO = new FileVO();
            fileVO.setId(file.getId());
            fileVO.setFormat(file.getFormat());
            return fileVO;
        }).collect(Collectors.toList());
        itemVO.setAttachments(attachments);

        //enrich 预览图信息
        List<FileVO> previews = map.getOrDefault(EFileType.PREVIEW.getType(), new ArrayList<>()).stream().map(file -> {
            FileVO fileVO = FileVO.fromFile(file);
            fileVO.setLink(GetUrl(file.getBucket(), file.getKey() + file.getName() + "." + file.getSuffix()));
            return fileVO;
        }).collect(Collectors.toList());
        if (previews.size() == 0) {
            previews.add(itemVO.getMain());
        }
        itemVO.setPreviews(previews);

        return itemVO;
    }

    /**
     * 组装item的附件信息
     *
     * @param itemVO itemvo
     */
    public void enrichAttach(ItemVO itemVO) {
        //item file信息
        QueryWrapper<File> fileQueryWrapper = new QueryWrapper<>();
        fileQueryWrapper.eq(SQLConstant.FILE_RESC_ID, itemVO.getId());
        fileQueryWrapper.eq(SQLConstant.FILE_TYPE, EFileType.ATTACHMENT.getType());
        List<File> files = fileService.list(fileQueryWrapper);

        List<FileVO> attachments = files.stream().map(file -> {
            FileVO fileVO = FileVO.fromFile(file);
            fileVO.setId(file.getId());
            fileVO.setFormat(file.getFormat());
            fileVO.setLink(GetUrl(file.getBucket(), file.getKey() + file.getName() + "." + file.getSuffix()));
            return fileVO;
        }).collect(Collectors.toList());
        itemVO.setAttachments(attachments);
    }

    @Override
    public Boolean saveItem(String name, String alias) {
        Item item = new Item();
        item.setName(name);
        item.setAlias(alias);
        item.setType("model");
        item.setCatId(7L);
        item.setDesp(null);
        item.setPrice(8.0);
        item.setAuthor("Jsson");
        item.setStatus("show");
        item.setMark("3d_sky");
        //保存数据库
        return this.save(item);
    }

}